import java.util.ArrayList;
import java.util.List;

/**
 * 加减法口算练习系统 - v0.3 测试模块
 * Calculation_System_V0_3_Test.java
 */

// 算式结构体
class Equation {
    int operand1;
    int operand2;
    char operator;
    int result;
    
    public Equation(int op1, int op2, char op, int res) {
        this.operand1 = op1;
        this.operand2 = op2;
        this.operator = op;
        this.result = res;
    }
}

// 练习题集合
class Exercise {
    List<Equation> equations;
    
    public Exercise() {
        equations = new ArrayList<>();
    }
    
    public void addEquation(Equation eq) {
        equations.add(eq);
    }
    
    public Equation getEquation(int index) {
        return equations.get(index);
    }
    
    public int size() {
        return equations.size();
    }
}

public class Calculation_System_V0_3_Test {
    
    public static void main(String[] args) {
        System.out.println("=== 加减法口算练习系统 v0.3 测试模块 ===");
        
        // 执行所有测试
        equationGeneratorTester();
        isEqualTester();
        occursInTester();
        exerciseGeneratorTester();
        
        System.out.println("\n=== 所有测试执行完成 ===");
    }
    
    // 测试函数 constructAdditionEquation 和 constructSubstractEquation
    static void equationGeneratorTester() {
        System.out.println("\n--- 测试算式生成函数 ---");
        boolean equal;
        Equation[] testData = new Equation[10];    // 存放测试数据的数组
        String[] expected = new String[10];        // 存放测试数据的期望结果
        int succeed = 0, failed = 0, executed = 0; // 分别是测试通过、测试失败、已执行测试的数量
        
        // 建立10个加法算式作为测试数据
        // 9+90, 15+77, 21+79, 33+66, 47+35, 51+49, 63+17, 71+8, 84+16, 97+3
        testData[0] = constructAdditionEquation(9, 90);
        expected[0] = "9+90=99";
        
        testData[1] = constructAdditionEquation(15, 77);
        expected[1] = "15+77=92";
        
        testData[2] = constructAdditionEquation(21, 79);
        expected[2] = "21+79=100";
        
        testData[3] = constructAdditionEquation(33, 66);
        expected[3] = "33+66=99";
        
        testData[4] = constructAdditionEquation(47, 35);
        expected[4] = "47+35=82";
        
        testData[5] = constructAdditionEquation(51, 49);
        expected[5] = "51+49=100";
        
        testData[6] = constructAdditionEquation(63, 17);
        expected[6] = "63+17=80";
        
        testData[7] = constructAdditionEquation(71, 8);
        expected[7] = "71+8=79";
        
        testData[8] = constructAdditionEquation(84, 16);
        expected[8] = "84+16=100";
        
        testData[9] = constructAdditionEquation(97, 3);
        expected[9] = "97+3=100";
        
        // 对每个测试数据产生一个算式，与期望的字符串比较
        for (int i = 0; i < 10; i++) {
            equal = asString(testData[i]).equals(expected[i]);
            executed++;
            if (equal) {
                succeed++;
                System.out.println("测试通过: " + asString(testData[i]));
            } else {
                failed++;
                System.out.println("测试失败: 期望=" + expected[i] + ", 实际=" + asString(testData[i]));
            }
        }
        
        // 统计测试结果
        System.out.println("算式生成测试结果：");
        System.out.println("共执行了 " + executed + " 次测试数据，执行率是 " + (executed/10.0*100) + "%");
        System.out.println(succeed + " 测试数据通过，通过率是 " + (succeed/10.0*100) + "%");
        System.out.println(failed + " 测试数据失败，失败率是 " + (failed/10.0*100) + "%");
    }
    
    // 测试函数 bool isEqual (Equation eq1, eq2)
    static void isEqualTester() {
        System.out.println("\n--- 测试算式相等判断函数 ---");
        boolean equal;
        Equation[] testData = new Equation[4];    // 存放测试数据的数组
        Equation anEquation;
        int succeed = 0, failed = 0, executed = 0;
        
        // 建立4个加法、减法算式作为测试数据
        // 35+47, 47+35, 47-35, 47-34
        testData[0] = constructAdditionEquation(35, 47);
        testData[1] = constructAdditionEquation(47, 35);
        testData[2] = constructSubstractEquation(47, 35);
        testData[3] = constructSubstractEquation(47, 34);
        
        // 测试1：47+35 应该等于 testData[1]
        anEquation = constructAdditionEquation(47, 35);
        executed++;
        equal = isEqual(anEquation, testData[1]);
        if (equal) {
            succeed++;
            System.out.println("测试成功: 算式" + asString(anEquation) + "等于算式" + asString(testData[1]));
        } else {
            failed++;
            System.out.println("测试失败: 算式" + asString(anEquation) + "应该等于算式" + asString(testData[1]));
        }
        
        // 测试2：47-35 应该不等于 47+35
        executed++;
        equal = isEqual(testData[2], testData[1]);
        if (!equal) {
            succeed++;
            System.out.println("测试成功: 算式" + asString(testData[2]) + "不等于算式" + asString(testData[1]));
        } else {
            failed++;
            System.out.println("测试失败: 算式" + asString(testData[2]) + "应该不等于算式" + asString(testData[1]));
        }
        
        // 测试3：47-34 应该不等于 47-35
        executed++;
        equal = isEqual(testData[3], testData[2]);
        if (!equal) {
            succeed++;
            System.out.println("测试成功: 算式" + asString(testData[3]) + "不等于算式" + asString(testData[2]));
        } else {
            failed++;
            System.out.println("测试失败: 算式" + asString(testData[3]) + "应该不等于算式" + asString(testData[2]));
        }
        
        System.out.println("算式相等测试结果：通过 " + succeed + "，失败 " + failed + "，执行 " + executed);
    }
    
    // 测试函数 bool occursIn (anEquation, equationArray)
    static void occursInTester() {
        System.out.println("\n--- 测试算式存在判断函数 ---");
        boolean equal;
        Equation eq, test_eq;
        Exercise eqArray = new Exercise();
        
        // 生成7个算式：25+35=，36-19=，98+1=，22+18=，71-19=，62-37=，44+52=
        eq = constructAdditionEquation(25, 35);
        eqArray.addEquation(eq);
        
        eq = constructSubstractEquation(36, 19);
        eqArray.addEquation(eq);
        
        eq = constructAdditionEquation(98, 1);
        eqArray.addEquation(eq);
        
        eq = constructAdditionEquation(22, 18);
        eqArray.addEquation(eq);
        
        eq = constructSubstractEquation(71, 19);
        eqArray.addEquation(eq);
        
        eq = constructSubstractEquation(62, 37);
        eqArray.addEquation(eq);
        
        eq = constructAdditionEquation(44, 52);
        eqArray.addEquation(eq);
        
        int succeed = 0, failed = 0, executed = 0;
        
        // 测试1：在数组的首部出现
        test_eq = constructAdditionEquation(25, 35);
        executed++;
        equal = occursIn(test_eq, eqArray);
        if (equal) {
            succeed++;
            System.out.println("测试成功: 算式在数组首部找到");
        } else {
            failed++;
            System.out.println("测试失败: 算式应该在数组首部");
        }
        
        // 测试2：在数组的末尾出现
        test_eq = constructAdditionEquation(44, 52);
        executed++;
        equal = occursIn(test_eq, eqArray);
        if (equal) {
            succeed++;
            System.out.println("测试成功: 算式在数组末尾找到");
        } else {
            failed++;
            System.out.println("测试失败: 算式应该在数组末尾");
        }
        
        // 测试3：在数组的中部出现
        test_eq = constructSubstractEquation(71, 19);
        executed++;
        equal = occursIn(test_eq, eqArray);
        if (equal) {
            succeed++;
            System.out.println("测试成功: 算式在数组中部找到");
        } else {
            failed++;
            System.out.println("测试失败: 算式应该在数组中部");
        }
        
        // 测试4：不在数组中出现
        test_eq = constructAdditionEquation(14, 5);
        executed++;
        equal = occursIn(test_eq, eqArray);
        if (!equal) {
            succeed++;
            System.out.println("测试成功: 算式不在数组中");
        } else {
            failed++;
            System.out.println("测试失败: 算式不应该在数组中");
        }
        
        System.out.println("算式存在测试结果：通过 " + succeed + "，失败 " + failed + "，执行 " + executed);
    }
    
    // 测试练习题生成函数
    static void exerciseGeneratorTester() {
        System.out.println("\n--- 测试练习题生成函数 ---");
        
        // 生成50道练习题
        Exercise exercise = generateExerciseOfMixedEquations();
        
        int succeed = 0, failed = 0, executed = 0;
        
        // 测试1：检查题目数量是否为50
        executed++;
        if (exercise.size() == 50) {
            succeed++;
            System.out.println("测试通过: 题目数量为50");
        } else {
            failed++;
            System.out.println("测试失败: 题目数量应为50，实际为" + exercise.size());
        }
        
        // 测试2：检查是否有重复算式
        executed++;
        boolean hasDuplicate = false;
        for (int i = 0; i < exercise.size(); i++) {
            for (int j = i + 1; j < exercise.size(); j++) {
                if (isEqual(exercise.getEquation(i), exercise.getEquation(j))) {
                    hasDuplicate = true;
                    break;
                }
            }
            if (hasDuplicate) break;
        }
        
        if (!hasDuplicate) {
            succeed++;
            System.out.println("测试通过: 没有重复算式");
        } else {
            failed++;
            System.out.println("测试失败: 存在重复算式");
        }
        
        // 测试3：检查所有算式结果都在0-100范围内
        executed++;
        boolean allInRange = true;
        for (int i = 0; i < exercise.size(); i++) {
            Equation eq = exercise.getEquation(i);
            if (eq.result < 0 || eq.result > 100) {
                allInRange = false;
                System.out.println("算式超出范围: " + asString(eq));
                break;
            }
        }
        
        if (allInRange) {
            succeed++;
            System.out.println("测试通过: 所有算式结果在0-100范围内");
        } else {
            failed++;
            System.out.println("测试失败: 有算式结果超出0-100范围");
        }
        
        // 测试4：检查答案正确性
        executed++;
        boolean allCorrect = true;
        for (int i = 0; i < exercise.size(); i++) {
            Equation eq = exercise.getEquation(i);
            int correctResult;
            if (eq.operator == '+') {
                correctResult = eq.operand1 + eq.operand2;
            } else {
                correctResult = eq.operand1 - eq.operand2;
            }
            
            if (eq.result != correctResult) {
                allCorrect = false;
                System.out.println("答案错误: " + asString(eq) + " 正确结果应为" + correctResult);
                break;
            }
        }
        
        if (allCorrect) {
            succeed++;
            System.out.println("测试通过: 所有题目答案正确");
        } else {
            failed++;
            System.out.println("测试失败: 有题目答案错误");
        }
        
        System.out.println("练习题生成测试结果：通过 " + succeed + "，失败 " + failed + "，执行 " + executed);
    }
    
    // ========== 被测试的函数 ==========
    
    // 构造加法算式
    static Equation constructAdditionEquation(int op1, int op2) {
        int result = op1 + op2;
        return new Equation(op1, op2, '+', result);
    }
    
    // 构造减法算式
    static Equation constructSubstractEquation(int op1, int op2) {
        int result = op1 - op2;
        return new Equation(op1, op2, '-', result);
    }
    
    // 算式转字符串
    static String asString(Equation eq) {
        return eq.operand1 + "" + eq.operator + "" + eq.operand2 + "=" + eq.result;
    }
    
    // 判断两个算式是否相等
    static boolean isEqual(Equation eq1, Equation eq2) {
        return eq1.operand1 == eq2.operand1 && 
               eq1.operand2 == eq2.operand2 && 
               eq1.operator == eq2.operator;
    }
    
    // 判断算式是否在数组中
    static boolean occursIn(Equation eq, Exercise eqArray) {
        for (int i = 0; i < eqArray.size(); i++) {
            if (isEqual(eq, eqArray.getEquation(i))) {
                return true;
            }
        }
        return false;
    }
    
    // 生成混合加减法练习题
    static Exercise generateExerciseOfMixedEquations() {
        Exercise exercise = new Exercise();
        int count = 0;
        
        while (count < 50) {
            // 随机选择加法或减法（各50%概率）
            boolean isAddition = Math.random() > 0.5;
            Equation equation;
            
            if (isAddition) {
                // 生成加法题
                int n, m, result;
                do {
                    n = (int)(Math.random() * 100) + 1;
                    m = (int)(Math.random() * 100) + 1;
                    result = n + m;
                } while (result > 100); // 加法算式的和不能超过100
                equation = constructAdditionEquation(n, m);
            } else {
                // 生成减法题
                int n, m, result;
                do {
                    n = (int)(Math.random() * 100) + 1;
                    m = (int)(Math.random() * 100) + 1;
                    result = n - m;
                } while (result < 0); // 减法算式的差不能小于0
                equation = constructSubstractEquation(n, m);
            }
            
            // 检查算式是否重复
            if (!occursIn(equation, exercise)) {
                exercise.addEquation(equation);
                count++;
            }
        }
        
        return exercise;
    }
}